#include "RangeObject.h"

OBJECT_DEFINE_START (RangeObject, range_object)

void
range_object_init (RangeObject* obj)
{
        number_object_init (NUMBER_OBJECT (obj));
        object_set_destory_func (obj, range_object_destory);
        obj->upper_range = 0;
        obj->range_state = RANGE_OBJECT_STATE_START;
}

void
range_object_destruction (RangeObject* obj)
{
        number_object_destruction (NUMBER_OBJECT (obj));
}

static RangeObjectEvent
range_object_catch_event (char ch)
{
        if (ch == '-')
                return RANGE_OBJECT_EVENT_DASH;
        if (ch == '\0')
                return RANGE_OBJECT_EVENT_ENDL;
        if (ch >= '0' && ch <= '9')
                return RANGE_OBJECT_EVENT_NUMBER;
        else
                return RANGE_OBJECT_EVENT_OTHER;
}

bool
range_object_is_number_in_range (RangeObject* obj, int number)
{
        if (!obj) {
                OBJECT_ERROR_TOOL (RangeObject,
                                   is_number_in_range,
                                   "对象为空！\n");
                return false;
        }
        if (NUMBER_OBJECT (obj)->number_type == VALUE_TYPE_NUMBER) {
                OBJECT_ERROR_TOOL (RangeObject,
                                   is_number_in_range,
                                   "不是范围对象，不可比较范围。\n");
                return false;
        }
        if (NUMBER_OBJECT (obj)->number <= number && obj->upper_range >= number)
                return true;
        return false;
}

int
range_object_analysis_range (RangeObject* obj, ObjectStringApplication* range)
{
        char             buf[2]     = {'\0', '\0'}, *str_tmp;
        bool             is_refresh = false;
        ObjectString*    tmp;
        RangeObjectEvent event;
        if (!obj || !range) {
                OBJECT_ERROR_TOOL (RangeObject,
                                   analysis_range,
                                   "参数传入不完整！\n");
                return 1;
        }

        object_addref (range);

        object_string_application_rewind (range);

        tmp = object_string_new ();
reanalysis:
        if (obj->range_state != RANGE_OBJECT_STATE_FAILED) {
                buf[0] = object_string_application_iter (range);
                event  = range_object_catch_event (buf[0]);
        }
        switch (obj->range_state) {
        case RANGE_OBJECT_STATE_START: {
                if (event == RANGE_OBJECT_EVENT_NUMBER) {
                        object_string_append_string (tmp, buf);
                        obj->range_state = RANGE_OBJECT_STATE_RECV;
                } else if (event == RANGE_OBJECT_EVENT_OTHER) {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           analysis_range,
                                           "在字符串 '%s' 中出现未定义字符 "
                                           "'\033[01;31m%c\033[0m'。\n",
                                           object_string_get_string (
                                                   OBJECT_STRING (range)),
                                           buf[0]);
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                } else {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           analysis_range,
                                           "字符串 '\033[01;33m~~~^\033[0m%s' "
                                           "起始应为数字。\n",
                                           object_string_get_string (
                                                   OBJECT_STRING (range)));
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                }
                break;
        }
        case RANGE_OBJECT_STATE_RECV: {
                if (event == RANGE_OBJECT_EVENT_NUMBER) {
                        object_string_append_string (tmp, buf);
                } else if (event == RANGE_OBJECT_EVENT_DASH && !is_refresh) {
                        is_refresh       = true;
                        obj->range_state = RANGE_OBJECT_STATE_REFRESH;
                } else if (event == RANGE_OBJECT_EVENT_DASH && is_refresh) {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           range_object,
                                           "不可出现第二个 '-'。\n");
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                } else if (event == RANGE_OBJECT_EVENT_OTHER) {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           analysis_range,
                                           "在字符串 '%s' 中出现未定义字符 "
                                           "'\033[01;31m%c\033[0m'。\n",
                                           object_string_get_string (
                                                   OBJECT_STRING (range)),
                                           buf[0]);
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                } else {
                        /*RANGE_OBJECT_EVENT_ENDL*/
                        obj->range_state = RANGE_OBJECT_STATE_ENDL;
                }
                break;
        }
        case RANGE_OBJECT_STATE_REFRESH: {
                if (event == RANGE_OBJECT_EVENT_NUMBER) {
                        number_object_set_number (
                                NUMBER_OBJECT (obj),
                                (int)strtol (tmp->charset, &str_tmp, 10));
                        object_string_set_string (tmp, buf);
                        obj->range_state = RANGE_OBJECT_STATE_RECV;
                } else if (event == RANGE_OBJECT_EVENT_OTHER) {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           analysis_range,
                                           "在字符串 '%s' 中出现未定义字符 "
                                           "'\033[01;31m%c\033[0m'。\n",
                                           object_string_get_string (
                                                   OBJECT_STRING (range)),
                                           buf[0]);
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                } else if (event == RANGE_OBJECT_EVENT_ENDL) {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           analysis_range,
                                           "字符串 '%s\033[01;31m^~~~\033[0m' "
                                           "提前结束！\n",
                                           object_string_get_string (
                                                   OBJECT_STRING (range)));
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                } else {
                        OBJECT_ERROR_TOOL (RangeObject,
                                           analysis_range,
                                           "不可同时出现两个 "
                                           "'\033[01;31m-\033[0m'！\n");
                        obj->range_state = RANGE_OBJECT_STATE_FAILED;
                }
                break;
        }
        case RANGE_OBJECT_STATE_FAILED:
                OBJECT_ERROR_TOOL (RangeObject,
                                   analysis_range,
                                   "范围数值解析出错！\n");
                object_unref (tmp);
                object_unref (range);
                return 1;
        case RANGE_OBJECT_STATE_ENDL: {
                if (is_refresh) {
                        number_object_set_type (NUMBER_OBJECT (obj), true);
                        obj->upper_range =
                                (int)strtol (tmp->charset, &str_tmp, 10);
                        if (NUMBER_OBJECT (obj)->number >= obj->upper_range) {
                                OBJECT_ERROR_TOOL (
                                        RangeObject,
                                        analysis_range,
                                        "数据范围前项 "
                                        "(\033[01;31m%d\033[0m) 大于等于后项 "
                                        "(\033[01;33m%d\033[0m)！\n",
                                        NUMBER_OBJECT (obj)->number,
                                        obj->upper_range);
                                obj->range_state = RANGE_OBJECT_STATE_FAILED;
                                break;
                        }
                } else {
                        number_object_set_number (
                                NUMBER_OBJECT (obj),
                                (int)strtol (tmp->charset, &str_tmp, 10));
                }
                object_unref (tmp);
                object_unref (range);
                return 0;
        }
        default:
                OBJECT_ERROR_TOOL (RangeObject,
                                   analysis_range,
                                   "触发 switch 中的未定义行为。\n");
                break;
        }

        goto reanalysis;
}
